import cn.xnatural.app.util.DB
import cn.xnatural.app.{AppContext, ServerTpl}
import cn.xnatural.enet.event.EL
import cn.xnatural.http.HttpServer
import cn.xnatural.sched.Sched
import ctrl.{MainCtrl, TestCtrl}

import java.time.Duration
import java.util.function.BiConsumer


@main def main: Unit = {
  val app = new AppContext().addSource(
    sched(), db(), web()
  ).start()
}


def sched(): ServerTpl = {
  new ServerTpl("sched") {
    lazy val sched = new Sched(attrs, exec).init

    @EL(name = Array("sys.starting"), async = true)
    def start(): Unit = {
      exposeBean(sched)
      ep.fire(name + ".started")
    }

    @EL(name = Array("sched.after"))
    def after(duration: Duration, fn: Runnable): Unit = {
      sched.after(duration, fn)
    }

    @EL(name = Array("sys.stopping"), async = true)
    def stop(): Unit = {
      sched.stop()
    }
  }
}

def web(): ServerTpl = {
  new ServerTpl("web") {
    lazy val server = new HttpServer(attrs(), exec)

    @EL(name = Array("sys.starting"), async = true)
    def start(): Unit = {
      server.ctrls(classOf[MainCtrl], classOf[TestCtrl])
      server.start()
      server.enabled = false
    }

    @EL(name = Array("sys.started"), async = true)
    def started(): Unit = {
      server.getCtrls.forEach(ctrl => exposeBean(ctrl))
      server.enabled = true
    }

    @EL(name = Array("sys.stop"))
    def stop(): Unit = {
      server.stop()
    }
  }
}

def db(): ServerTpl = {
  new ServerTpl("db_local") { //数据库 db_local
    lazy val repo = new DB(getStr("url", null))

    @EL(name = Array("sys.starting"), async = true)
    def start(): Unit = {
      attrs().forEach(new BiConsumer[String, Any] {
        def accept(k:String, v:Any): Unit = {
          repo.dsAttr(k, v)
        }
      })
      exposeBean(repo)
      ep.fire(name + ".started")
    }

    @EL(name = Array("sys.stopping"), async = true, order = 2f)
    def stop(): Unit = {
      repo.close()
    }
  }
}

